/*
 *  This file is part of LifeBudget - Copyright 2010 Clifton Eaton
 *  ------------------------------------------------------------------
 *  LifeBudget is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  LifeBudget is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with LifeBudget.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.lifebudget.app.client.mvc.controller;

import java.util.List;

import org.lifebudget.app.client.events.AppEvents;
import org.lifebudget.app.client.mvc.model.Category;
import org.lifebudget.app.client.mvc.view.CategoriesView;
import org.lifebudget.app.client.service.CategoryService;
import org.lifebudget.app.client.service.CategoryServiceAsync;

import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.mvc.Dispatcher;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * The controller for handling Category events and serving 
 * Category related views.
 */
public class CategoriesController extends Controller {

	/** The categories view. */
	private CategoriesView categoriesView;
	
	/** The category service. */
	private CategoryServiceAsync categoryService;

	/**
	 * Instantiates a new categories controller, registering all of the
	 * events handled by the controller.
	 */
	public CategoriesController() {
		registerEventTypes(AppEvents.Init);
		registerEventTypes(AppEvents.CategoryChangesCommitted);
		registerEventTypes(AppEvents.CategoryArchived);
	}

	/* (non-Javadoc)
	 * @see com.extjs.gxt.ui.client.mvc.Controller#initialize()
	 */
	public void initialize() {
		categoryService = GWT.create(CategoryService.class);
		categoriesView = new CategoriesView(this);
	}

	/* (non-Javadoc)
	 * @see com.extjs.gxt.ui.client.mvc.Controller#handleEvent(com.extjs.gxt.ui.client.mvc.AppEvent)
	 */
	@Override
	public void handleEvent(AppEvent event) {
		if (event.getType() == AppEvents.Init) {
			// GWT.log("CategoriesController received AppEvent Init, forwarding to view");
			onInit(event);
		}
		if (event.getType() == AppEvents.CategoryChangesCommitted) {
			// GWT.log("CategoriesController received AppEvent CategoryChangesComitted");
			onCategoryChangesCommitted(event);
		}
		if (event.getType() == AppEvents.CategoryArchived) {
			// GWT.log("CategoriesController received AppEvent CategoryChangesComitted");
			onCategoryArchived(event);
		}

	}

	/**
	 * Handles the <code>CategoryArchived</code> event, invoking the service to "archive"
	 * the {@link Category} and notifying the event bus that categories need refreshing.
	 *
	 * @param event the <code>CategoryArchived</code> event.
	 */
	private void onCategoryArchived(AppEvent event) {
		Category category = event.getData();
		categoryService.removeCategory(category, new AsyncCallback<List<Category>>() {
			@Override
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
				Dispatcher.get().dispatch(AppEvents.Error, "Unable to archive Category");
			}

			@Override
			public void onSuccess(List<Category> result) {
				Dispatcher.get().dispatch(AppEvents.RefreshCategory, result);
			}
		});
	}

	/**
	 * Handles the CategoryChangesCommitted event, calling the service to update
	 * the Categories and then forwarding the updated set back to the categories view.
	 *
	 * @param event the CategoryChangesCommitted event.
	 */
	private void onCategoryChangesCommitted(final AppEvent event) {
		List<Category> categories = (List<Category>) event.getData();
		categoryService.updateCategories(categories, new AsyncCallback<List<Category>>() {
			@Override
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
				Dispatcher.get().dispatch(AppEvents.Error, "Unable to update Categories");
			}

			@Override
			public void onSuccess(List<Category> result) {
				event.setData(result);
				forwardToView(categoriesView, event);

			}
		});

	}

	/**
	 * Handles the Init event, retrieving all {@link Category} objects and then 
	 * forwarding the event and data to the Categories view.
	 *
	 * @param event the Init event
	 */
	public void onInit(AppEvent event) {

		categoryService.getAllCategories(false, new AsyncCallback<List<Category>>() {

			@Override
			public void onFailure(Throwable caught) {
				Dispatcher.forwardEvent(AppEvents.Error, caught);
			}

			@Override
			public void onSuccess(List<Category> result) {
				// GWT.log("Forwarding to categories View");
				forwardToView(categoriesView, AppEvents.Init, result);

			}

		});

	}
}